﻿using System;
using System.Collections.Generic;
using System.Linq;
using HalconDotNet;

namespace ALC.Core.Camera
{
    public class ImageCollector
    {
        #region private fields

        // Todo: define camera names
        private static readonly string[] CameraNames = { };
        
        
        private readonly SortedDictionary<string, HImage> _imageBuffer = new SortedDictionary<string, HImage>();
        private HCamera[] _cameras;
        /// <summary>
        /// flag to indicate whether the image is the
        /// first one to received in this loop
        /// </summary>
        private bool _isFirstImage = true;

        #endregion

        #region events

        public event Action<IList<HImage>> ImagesCollectionDone;

        public event Action FirstImageReceived;

        #endregion

        #region ctor
        
        public ImageCollector(HCamera[] cameras)
        {
            _cameras = cameras;

            foreach (var camera in cameras)
            {
                camera.SingleImageAcquired += ReceiveSingleImage;
                camera.OpenAndGrabContinuously();
            }
        }

        #endregion

        public static ImageCollector Instance { get; private set; }
        
        #region api

        public static void Init()
        {
            var cameras = new List<HCamera>();
            foreach (var cameraName in CameraNames)
            {
                cameras.Add(new HCamera(cameraName));
            }
            
            Instance = new ImageCollector(cameras.ToArray());
        }

        public static void CloseCameras()
        {
            foreach (var camera in Instance._cameras)
            {
                camera?.StopAndClose();
            }
        }

        #endregion

        #region impl

        private void ReceiveSingleImage(string cameraName, HImage image)
        {
            _imageBuffer[cameraName] = image;
            if (_imageBuffer.Count == _cameras.Length)
            {
                OnImagesCollectionDone(_imageBuffer.Values.ToList());
            }

            if (_isFirstImage)
            {
                _isFirstImage = false;
                OnFirstImageReceived();
            }
            
        }


        protected virtual void OnImagesCollectionDone(IList<HImage> images)
        {
            ImagesCollectionDone?.Invoke(images);
            ClearImageBuffer();
            _isFirstImage = true;
        }

        private void ClearImageBuffer()
        {
            _imageBuffer.Clear();
        }

        protected virtual void OnFirstImageReceived()
        {
            FirstImageReceived?.Invoke();
        }
        

        #endregion 
    }
}